﻿#requires -RunAsAdministrator
#requires -Module Pester

if (-not (test-path Variable:\pester)) {
    throw "script must be run with Invoke-Pester.ps1"
}

if (-not (Test-Path -Path Variable:\DevboardTestContent)) {
    Write-Warning "Run $PSScriptRoot\SetupTestContent.ps1 first"
    Write-Warning "Skipping all tests"
    return
}

# import the scripts that we need
$root = resolve-path $PSScriptRoot\..\DevBoard

. "$root\BspManifest.ps1"


Describe "Create a BSP from a source image" {

    Context "end-to-end test" {
        
        Set-StrictMode -Version 3

        $sourceWim = $DevboardTestContent["WimFile"]
        $sourceBsp = $DevboardTestContent["BspRoot"]

        $testRoot = Convert-Path "TestDrive:\"
    
        $testBspManifest = Join-Path $testRoot "manifest.xml"
        $mockBspManifest = Join-Path $sourceBsp "manifest.xml"

        $outputWim =   Join-Path $testRoot "output.wim"
        $mountDir =    Join-Path $testRoot "mount"

        Write-Warning "output WIM @ $outputWim"
        Write-Warning "Mount directory is $mountDir"

        $ignore = Get-Content $sourceBsp\.ignore
        $expectedCount = (
            gci -Recurse -Path $sourceBsp -Filter *.inf |
            Where-Object {
                $trimmed = $_.FullName -replace ([regex]::Escape("$sourceBsp")),""
                $ignore -notcontains $trimmed
            }
            ).Count

        # import the BSP
        $bsp = New-BspManifest -RootDirectory $sourceBsp -Import

        It "Imports the right number of INFs" {
            $bsp.Drivers.Count | Should Be $expectedCount
        }

        It "lets me add firmware and tools" {
            {
                $bsp.AddContent("Firmware", $DevboardTestContent["FirmwareFile"])
                
                $name = split-path -Leaf $DevboardTestContent["FirmwareFile"]
                $bsp.Items.ContainsKey($name) | Should Be $true
            
            } | Should Not Throw

            {
                $bsp.AddContent("UefiTool", $DevboardTestContent["UefiTools"])

                $name = split-path -Leaf $DevboardTestContent["UefiTools"]
                $bsp.Items.ContainsKey($name) | Should Be $true

            } | Should Not Throw
        }

        It "exports the manifest correctly" {
            { $bsp.Save($testBspManifest) } | Should Not Throw
            $testBspManifest | Should Exist
        }

        . "$root\DevboardImage.ps1" -WhatIf

        It "succesfully creates the target image" {

            # don't dismount the image after New-DevboardImage runs so that we don't 
            # have to waste time remounting it to look inside
            Mock Dismount-WindowsImage -parameterFilter {
                    (Microsoft.Powershell.Management\Test-Path Variable:\Save) -and ($Save.IsPresent)
                } -MockWith {
                    write-host "MOCK Dismount-WindowsImage called"
                }
            
            # Mocks to make the BSP manifest generated in TestDrive:\... look like it's in 
            # the root of the source BSP
            Mock Test-Path -parameterFilter {$Path -eq $mockBspManifest} -mockWith {$true}

            Mock Get-Content -parameterFilter {$Path -eq $mockBspManifest} -mockWith {
                $PSBoundParameters["Path"] = $testBspManifest
                Microsoft.PowerShell.Management\Get-Content @PSBoundParameters
            }

            Mock Resolve-Path -parameterFilter {$Path -eq $mockBspManifest} -mockWith {
                $mockBspManifest
            }
            
                        
            { 
              New-DevboardImage `
                -SourcePath $sourceWim `
                -Index 2 `
                -BspManifest $mockBspManifest `
                -MountDir $mountDir `
                -Destination $outputWim `
            } | Should Not Throw

            # remove all of the Mocks before continuing, as some of these conflict
            # with the Assertion functions.
            Clear-Mocks
            
            $outputWim | Should Exist
        }

        # It "dismounts the WIM" {
        #     (gci -Path $mountDir -Recurse).Count | Should Be 0
        # }

        # It "produces a valid WIM" {
        #     {Mount-WindowsImage -ImagePath $outputWim -Index 1 -Path $mountDir} | Should Not Throw
        # }

        It "Applies the right number of drivers" {
            (Get-WindowsDriver -Path $mountDir |
                Where-Object {$_.ProviderName -ne "Microsoft"}).Count | Should Be $expectedCount
        }

        It "Copies the firmware file" {
            "$mountDir\tools\firmware\BIOSUPDATE.fv" | Should Exist
        }

        It "Copies the UEFI tools" {
            "$mountDir\tools\uefi\talk2i2c.efi" | Should Exist
        }
        
        Dismount-WindowsImage -Path $mountDir -Save -ErrorAction SilentlyContinue | Out-Null

        if ($DevboardTestContent["SaveOutputWim"]) {
            Write-Warning "Moving $outputWim to $ENV:TEMP"
            Move-Item -Path $outputWim -Destination $ENV:TEMP
            Move-Item -Path $testRoot\dism.log -Destination $ENV:TEMP
        }
    }
}